package io.noties.markwon;


import com.noties.markwon.annotation.NonNull;
import com.noties.markwon.annotation.Nullable;
import com.noties.markwon.utils.LogUtils;
import com.noties.markwon.wrapper.text.BufferType;
import com.noties.markwon.wrapper.text.PrecomputedTextCompat;
import com.noties.markwon.wrapper.text.Spanned;

import java.lang.ref.WeakReference;
import java.util.concurrent.Executor;
import ohos.agp.components.Text;
import ohos.ai.tts.TtsClient;

/**
 * Please note this class requires `androidx.core:core` artifact being explicitly added to your dependencies.
 * Please do not use with `markwon-recycler` as it will lead to bad item rendering (due to async nature)
 *
 * @see Markwon.TextSetter
 * @since 4.1.0
 */
public class PrecomputedTextSetterCompat implements Markwon.TextSetter {
    private static final String TAG = "PrecomputedTextSetterCompat";
    /**
     * @param executor for background execution of text pre-computation
     */
    @NonNull
    public static PrecomputedTextSetterCompat create(@NonNull Executor executor) {
        return new PrecomputedTextSetterCompat(executor);
    }

    private final Executor executor;

    @SuppressWarnings("WeakerAccess")
    PrecomputedTextSetterCompat(@NonNull Executor executor) {
        this.executor = executor;
    }

    @Override
    public void setText(
            @NonNull Text textView,
            @NonNull final Spanned markdown,
            @NonNull final BufferType bufferType,
            @NonNull final Runnable onComplete) {

        // insert version check and do not execute on a device < Build.VERSION_CODES.LOLLIPOP(21)

        if (Integer.getInteger(TtsClient.getInstance().getVersion().get()) < 21) {
            // it's still no-op, so there is no need to start background execution
            applyText(textView, markdown, bufferType, onComplete);
            return;
        }

        final WeakReference<Text> reference = new WeakReference<>(textView);
        executor.execute(() -> {
            try {
                final PrecomputedTextCompat precomputedTextCompat = precomputedText(reference.get(), markdown);
                if (precomputedTextCompat != null) {
                    applyText(reference.get(), precomputedTextCompat, bufferType, onComplete);
                }
            } catch (Throwable t) {
                LogUtils.e(TAG, t.getMessage());
                // apply initial markdown
                applyText(reference.get(), markdown, bufferType, onComplete);
            }
        });
    }

    @Nullable
    private static PrecomputedTextCompat precomputedText(@Nullable Text textView, @NonNull Spanned spanned) {

        if (textView == null) {
            return null;
        }

        final PrecomputedTextCompat.Params params;
        // insert version check and do not execute on a device Build.VERSION_CODES.P(28)

        if (Integer.getInteger(TtsClient.getInstance().getVersion().get()) >= 28) {
            // use native parameters on P
            params = new PrecomputedTextCompat.Params(textView);
        } else {

            final PrecomputedTextCompat.Params.Builder builder =
                    new PrecomputedTextCompat.Params.Builder(textView);

            // please note that text-direction initialization is omitted
            // by default it will be determined by the first locale-specific character

            // insert version check and do not execute on a device Build.VERSION_CODES.M(23)

            if (Integer.getInteger(TtsClient.getInstance().getVersion().get()) >= 23) {
                // another miss on API surface, this can easily be done by the compat class itself
                builder
                        .setBreakStrategy(textView)
                        .setHyphenationFrequency(textView);
            }

            params = builder.build();
        }

        return PrecomputedTextCompat.create(spanned, params);
    }

    private static void applyText(
            @Nullable final Text textView,
            @NonNull final Spanned text,
            @NonNull final BufferType bufferType,
            @NonNull final Runnable onComplete) {
        if (textView != null) {
            // TODO YR textView.post
        /*    textView.post(new Runnable() {
                @Override
                public void run() {
                    textView.setText(text, bufferType);
                    onComplete.run();
                }
            });*/
        }
    }
}
